#include "sessionfriendarea.h"
#include "debug.h"
#include "mainwidget.h"
#include "model/datacenter.h"

SessionFriendArea::SessionFriendArea(QWidget *parent) : QScrollArea{parent}
{
    // 1. 进行必要的属性设置
    this->setWidgetResizable(true); // 设为 true 才能开启滚动效果
    // 设置滚动条样式
    this->verticalScrollBar()->setStyleSheet("QScrollBar:vertical { width: 2px; background-color: rgb(46, 46, 46);}");
    this->horizontalScrollBar()->setStyleSheet("QScrollBar:horizontal { height: 0px; }");
    this->setStyleSheet("QWidget { border: none;}");

    // 2. 把 widget 创建出来
    _container = new QWidget();
    _container->setFixedWidth(310);
    this->setWidget(_container);

    // 3. 给 widget 指定布局管理器
    QVBoxLayout *layout = new QVBoxLayout();
    layout->setContentsMargins(0, 0, 0, 0);
    layout->setSpacing(0);
    layout->setAlignment(Qt::AlignTop);
    _container->setLayout(layout);

#ifdef TEST_UI
    // 测试滚动效果
    // for (int i = 0; i < 50; i++)
    // {
    //     QPushButton *btn = new QPushButton();
    //     btn->setText("按钮");
    //     layout->addWidget(btn);
    // }
    QIcon icon(":/resource/image/defaultAvatar.png");
    for (int i = 0; i < 30; ++i)
    {
        this->addItem(SessionItemType, QString::number(i), icon, "张三" + QString::number(i),
                      "最后一条消息" + QString::number(i));
    }
#endif
}

void SessionFriendArea::clear()
{
    QLayout *layout = _container->layout();
    // 遍历布局管理器中的所有元素，并依次从布局管理器中删除
    for (int i = layout->count() - 1; i >= 0; i--) // 防止删除越界从后面向前遍历
    {
        // takeAt 用于删除对应下标的元素
        QLayoutItem *item = layout->takeAt(i);
        if (item->widget())
        {
            // 释放对象
            delete item->widget();
        }
    }
}

void SessionFriendArea::addItem(ItemType itemType, const QString &id, const QIcon &avatar, const QString &name,
                                const QString &text)
{
    SessionFriendItem *item = nullptr;
    if (itemType == SessionItemType)
    {
        item = new SessionItem(this, id, avatar, name, text);
    }
    else if (itemType == FriendItemType)
    {
        item = new FriendItem(this, id, avatar, name, text);
    }
    else if (itemType == ApplyItemType)
    {
        item = new ApplyItem(this, id, avatar, name);
    }
    else
    {
        LOG() << "错误的 ItemType！ItemType=" << itemType;
        return;
    }
    _container->layout()->addWidget(item);
}

void SessionFriendArea::clickItem(int index)
{
    if (index < 0 || index >= _container->layout()->count())
    {
        LOG() << "点击元素的下标超出范围！index=" << index;
        return;
    }
    QLayoutItem *layoutItem = _container->layout()->itemAt(index);
    if (layoutItem == nullptr || layoutItem->widget() == nullptr)
    {
        LOG() << "指定的元素不存在！index=" << index;
        return;
    }
    SessionFriendItem *item = dynamic_cast<SessionFriendItem *>(layoutItem->widget());
    item->select();
}

SessionFriendItem::SessionFriendItem(QWidget *owner, const QIcon &avatar, const QString &name, const QString &text)
    : owner(owner)
{
    this->setFixedHeight(70);
    this->setStyleSheet("QWidget { background-color: rgb(247, 247, 247); }");

    // 创建网格布局管理器
    QGridLayout *layout = new QGridLayout();
    layout->setContentsMargins(20, 0, 0, 0);
    layout->setHorizontalSpacing(10);
    layout->setVerticalSpacing(0);
    this->setLayout(layout);

    // 创建头像
    QPushButton *avatarBtn = new QPushButton();
    avatarBtn->setFixedSize(50, 50);
    avatarBtn->setIconSize(QSize(50, 50));
    avatarBtn->setIcon(avatar);
    avatarBtn->setStyleSheet("QPushButton {border: none;}");
    avatarBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

    // 创建名字
    QLabel *nameLabel = new QLabel();
    nameLabel->setText(name);
    nameLabel->setStyleSheet("QLabel { font-size: 18px; font-weight: 600; }");
    nameLabel->setFixedHeight(35);
    nameLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

    // 创建消息预览的 label
    messageLabel = new QLabel();
    messageLabel->setText(text);
    messageLabel->setFixedHeight(35);
    messageLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

    // 头像处于 0, 0 位置, 占据 2 行, 占据 2 列
    layout->addWidget(avatarBtn, 0, 0, 2, 2);
    // 名字处于 0, 2 位置, 占据 1 行, 占据 1 列
    layout->addWidget(nameLabel, 0, 2, 1, 8);
    // 消息预览处于 1, 2 位置, 占据 1 行, 占据 1 列
    layout->addWidget(messageLabel, 1, 2, 1, 8);
}

void SessionFriendItem::paintEvent(QPaintEvent *event)
{
    (void) event; // 消除告警
    QStyleOption opt;
    opt.initFrom(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}

void SessionFriendItem::mousePressEvent(QMouseEvent *event)
{
    (void) event;
    select();
}

void SessionFriendItem::enterEvent(QEnterEvent *event)
{
    (void) event;
    // 若当前这个 item 是选中状态，则背景颜色不受该逻辑影响
    if (this->selected)
    {
        return;
    }
    // 设置一个颜色更深的颜色
    this->setStyleSheet("QWidget { background-color: rgb(234, 234, 234);}");
}

void SessionFriendItem::leaveEvent(QEvent *event)
{
    (void) event;
    // 若当前这个 item 是选中状态，则背景颜色不受该逻辑影响
    if (this->selected)
    {
        return;
    }
    // 还原背景色
    this->setStyleSheet("QWidget { background-color: rgb(247, 247, 247);}");
}

void SessionFriendItem::select()
{
    // 鼠标点击 item 时触发该函数
    // 拿到所有的兄弟元素
    const QObjectList children = this->parentWidget()->children();
    for (QObject *child : children)
    {
        if (!child->isWidgetType())
        {
            // 判定是否是 widget
            continue;
        }
        // 是 widget，把 child 强转成 SessionFriendItem
        SessionFriendItem *item = dynamic_cast<SessionFriendItem *>(child);
        if (item->selected)
        {
            item->selected = false;
            item->setStyleSheet("QWidget { background-color: rgb(232, 232, 232); }");
        }
    }
    // 点击时修改背景色
    this->setStyleSheet("QWidget { background-color: rgb(210, 210, 210); }");
    this->selected = true;

    this->active();
}

void SessionFriendItem::active() {}

SessionItem::SessionItem(QWidget *owner, const QString &chatSessionId, const QIcon &avatar, const QString &name,
                         const QString &lastMessage)
    : SessionFriendItem(owner, avatar, name, lastMessage), _chatSessionId(chatSessionId), _text(lastMessage)
{
    // 处理最后一个消息的信号
    model::DataCenter *dataCenter = model::DataCenter::getInstance();
    connect(dataCenter, &model::DataCenter::updateLastMessage, this, &SessionItem::updateLastMessage);

    // 需要显示出未读消息的数目, 为了支持客户端重启之后, 未读消息仍然能正确显示.
    int unread = dataCenter->getUnread(chatSessionId);
    if (unread > 0)
    {
        // 存在未读消息
        this->messageLabel->setText(QString("[未读%1条] ").arg(unread) + _text);
    }
}

void SessionItem::active()
{
    // 点击后加载会话的历史消息列表
    LOG() << "点击 SessionItem 触发的逻辑！chatSessionId=" << _chatSessionId;

    // 加载会话历史消息
    MainWidget *mainWidget = MainWidget::getInstance();
    mainWidget->loadRecentMessage(_chatSessionId);

    // 清空未读消息，并更新显示
    model::DataCenter *dataCenter = model::DataCenter::getInstance();
    dataCenter->clearUnread(_chatSessionId);

    // 更新界面显示，把会话消息预览前面的 [未读x条] 内容删除
    this->messageLabel->setText(_text);
}

void SessionItem::updateLastMessage(const QString &chatSessionId)
{
    model::DataCenter *dataCenter = model::DataCenter::getInstance();

    // 1. 判定 chatSessionId 是否匹配
    if (_chatSessionId != chatSessionId)
    {
        // 当前 SessionItem 不是用户正在发送消息的 SessionItem
        return;
    }

    // 2.获取到最后一条消息
    QList<Message> *messageList = dataCenter->getRecentMessageList(chatSessionId);
    if (messageList == nullptr || messageList->size() == 0)
    {
        // 当前会话没有任何消息，无需更新
        return;
    }

    const Message &lastMessage = messageList->back();

    // 3. 明确显示的文本内容
    // 非文本类型由于只有 fileId ，直接显示 [图片]/[文件]/[语音]
    if (lastMessage.messageType == model::TEXT_TYPE)
    {
        _text = lastMessage.content;
    }
    else if (lastMessage.messageType == model::IMAGE_TYPE)
    {
        _text = "[图片]";
    }
    else if (lastMessage.messageType == model::FILE_TYPE)
    {
        _text = "[文件]";
    }
    else if (lastMessage.messageType == model::SPEECH_TYPE)
    {
        _text = "[语音]";
    }
    else
    {
        LOG() << "错误的消息类型！";
        return;
    }

    // 4. 把这个内容显示到界面上
    // 考虑 "未读消息" 的情况，判断当前消息会话是不是所选会话
    // 如果是，直接更新预览信息
    // 如果不是，增加 "[未读%1条]" 的前缀
    if (chatSessionId == dataCenter->getCurrentChatSessionId())
    {
        this->messageLabel->setText(_text);
    }
    else
    {
        int unread = dataCenter->getUnread(chatSessionId);
        if (unread > 0)
        {
            this->messageLabel->setText(QString("[未读%1条]").arg(unread) + _text);
        }
    }
}

FriendItem::FriendItem(QWidget *owner, const QString &userId, const QIcon &avatar, const QString &name,
                       const QString &description)
    : SessionFriendItem(owner, avatar, name, description), userId(userId)
{
}

void FriendItem::active()
{
    LOG() << "点击 FriendItem 触发的逻辑! userId=" << userId;
    MainWidget *mainWidget = MainWidget::getInstance();
    mainWidget->switchSession(userId);
}

ApplyItem::ApplyItem(QWidget *owner, const QString &userId, const QIcon &avatar, const QString &name)
    : SessionFriendItem(owner, avatar, name, ""), userId(userId)
{
    // 1. 移除父类的 messageLabel
    QGridLayout *layout = dynamic_cast<QGridLayout *>(this->layout());
    layout->removeWidget(messageLabel);
    delete messageLabel;

    // 2. 创建两个按钮
    QPushButton *acceptBtn = new QPushButton();
    acceptBtn->setText("同意");
    QPushButton *rejectBtn = new QPushButton();
    rejectBtn->setText("拒绝");

    // 3. 添加到布局管理器中
    layout->addWidget(acceptBtn, 1, 2, 1, 1);
    layout->addWidget(rejectBtn, 1, 3, 1, 1);

    // 4. 添加信号槽
    // connect(acceptBtn, &QPushButton::clicked, this, &ApplyItem::acceptFriendApply);
    // connect(rejectBtn, &QPushButton::clicked, this, &ApplyItem::rejectFriendApply);
}

void ApplyItem::active() { LOG() << "点击 ApplyItem 触发的逻辑! userId=" << userId; }
